package com.mo.filter;

import com.mo.constants.RedisPrefix;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;

@Component
public class TokenGatewayFilterFactory extends AbstractGatewayFilterFactory<TokenGatewayFilterFactory.Config> {
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    public TokenGatewayFilterFactory() {
        super(Config.class);
    }
    @Override
    public GatewayFilter apply(Config config) {
        //当有请求发生的时候就会执行该方法
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                //判断token
                if(config.required){
                    //想办法获取到请求路径中的token变量   http://localhost:xxx/xxx?a=1&b=zs&c=helo&token=xxx&token=xxx
                    String token = exchange.getRequest().getQueryParams().getFirst("token");
                    if(StringUtils.isEmpty(token)){
                        throw new RuntimeException("非法请求！！！");
                    }
                    //到redis里面判断该key是否存在
                    if(!redisTemplate.hasKey(RedisPrefix.TOKEN+token)){
                        throw new RuntimeException("token无效！！！");
                    }
                }
                //放行请求
                return chain.filter(exchange);
            }
        };
    }

    //就是吧配置文件中的配置项，转换到config对象的属性里面。
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("required");
    }

    public static class Config {
        private boolean required;

        public Config() {
        }

        public boolean isRequired() {
            return required;
        }

        public void setRequired(boolean required) {
            this.required = required;
        }

    }
}
